﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Mina.Core.Filterchain;
using Mina.Core.Session;
using Mina.Core.Buffer;
using Mina.Core.Write;

namespace SharpIM
{
    public class ServerSslFilter : Mina.Filter.Ssl.SslFilter
    {
        public ServerSslFilter(string certFile) : base(certFile) { }
        public ServerSslFilter(X509Certificate cert) : base(cert) { }
        public ServerSslFilter(string targetHost, X509CertificateCollection clientCertificates) : base(targetHost, clientCertificates) { }
        public override void MessageReceived(INextFilter nextFilter, IoSession session, object message)
        {
            var buffer = message as IoBuffer;
            var ssl = session.GetAttribute<bool?>("is_ssl_session");
            if (ssl == null && buffer != null)
            {
                //检查是否握手协议
                var protocol = buffer.Get();
                var version = buffer.Get();
                var length = buffer.GetInt16();
                session.SetAttribute("is_ssl_session", (ssl = protocol == 22 && version > 0 && length > 0));
                buffer.Position = 0;
            }
            if (IsSsl(session))
            {
                lock (this)
                {
                    if (delayedSslHandlerCreation != null)
                    {
                        delayedSslHandlerCreation.Invoke();
                        delayedSslHandlerCreation = null;
                    }
                    if (delayedHandshake != null)
                    {
                        delayedHandshake.Invoke();
                        delayedHandshake = null;
                    }
                }
                base.MessageReceived(nextFilter, session, message);
            }
            else
            {
                session.FilterChain.Remove(this);
                nextFilter.MessageReceived(session, message);
            }
        }
        public bool IsSsl(IoSession session)
        {
            var is_ssl_session = session.GetAttribute<bool?>("is_ssl_session");
            return is_ssl_session.HasValue && is_ssl_session.Value;
        }
        internal delegate void OnPostAddDelegate(IoFilterChain parent, string name, INextFilter nextFilter);
        internal delegate void OnPreAddDelegate(IoFilterChain parent, string name, INextFilter nextFilter);
        DelayedHandshake delayedHandshake;
        DelayedSslHandlerCreation delayedSslHandlerCreation;
        public override void OnPostAdd(IoFilterChain parent, string name, INextFilter nextFilter)
        {
            delayedHandshake = new DelayedHandshake { Action = base.OnPostAdd, Args = new object[] { parent, name, nextFilter } };
        }

        public override void OnCreateSslHandler(IoFilterChain parent, string name, INextFilter nextFilter)
        {
            delayedSslHandlerCreation = new DelayedSslHandlerCreation { Action = base.OnCreateSslHandler, Args = new object[] { parent, name, nextFilter } };
        }
        internal class DelayedHandshake
        {
            internal OnPostAddDelegate Action;
            internal object[] Args;
            public void Invoke()
            {
                Action.Invoke(Args[0] as IoFilterChain, Args[1] as string, Args[2] as INextFilter);
            }
        }
        internal class DelayedSslHandlerCreation
        {
            internal OnPreAddDelegate Action;
            internal object[] Args;
            public void Invoke()
            {
                Action.Invoke(Args[0] as IoFilterChain, Args[1] as string, Args[2] as INextFilter);
            }
        }
    }
}
